import uuid
from datetime import datetime

from chatbot.bot import conf
from chatbot.component.singleton import singleton


class Session(object):
    """
    机器人会话对象，每一个聊天窗就是一个会话
    """
    __slots__ = (
        'session_id',
        'bot',
        'visitor',
        'conversation',
        'channel',
        'start_time',
        'last_chat_time'
    )

    def __init__(self, session_id, bot, visitor, channel):
        self.session_id = session_id
        self.bot = bot
        self.visitor = visitor
        self.channel = channel
        self.conversation = {}
        self.start_time = datetime.now()

    def set_history_conversation(self, conversation):
        self.conversation['history'] = conversation

    def set_current_conversation(self, conversation):
        self.conversation['current'] = conversation
        self.start_time = conversation.start_time

    def set_cookie(self, request, response):
        cookie_visitor_id = request.COOKIES.get(conf.BOT_COOKIE_VISITOR_ID, '')
        visitor_id = str(self.visitor.id)
        if not cookie_visitor_id or cookie_visitor_id != visitor_id:
            response.set_cookie(conf.BOT_COOKIE_VISITOR_ID, visitor_id)


@singleton
class SessionManager(object):
    """
    管理机器人对话过程中的会话状态
    """
    sessions = {}

    def __init__(self, request, channel_id):
        self.get_session(request, channel_id)

    def add(self, session):
        if not session:
            return
        if not self.has_session(session.session_id):
            self.sessions[session.session_id] = session

    def has_session(self, session_id):
        return True and self.sessions.get(session_id, '')

    def remove(self, session):
        if not session:
            return
        if not self.has_session(session.session_id):
            return
        del self.sessions[session.session_id]

    def kickoff_timeout_session(self):
        now = datetime.now()
        for session in self.sessions:
            timeout = session.bot.get_timeout_interval() * 2
            if now - session.last_chat_time >= timeout:
                self.remove(session)

    def _get_session(self, session_id):
        return self.sessions.get(session_id, '')

    def get_session(self, request, channel_id) -> Session:
        http_session = request.session
        http_cookies = request.COOKIES

        session_id = http_session.get(conf.BOT_SESSION_ID, '')
        visitor_id = http_cookies.get(conf.BOT_COOKIE_VISITOR_ID, '')

        session = None
        visitor = None
        if session_id:
            session = self._get_session(session_id)
        else:
            session_id = str(uuid.uuid4()).replace('-', '')
            http_session[conf.BOT_SESSION_ID] = session_id

        if not session:
            from chatbot.service.init.bot_initialize import BotFactory
            from chatbot.models import ChatVisitor

            bot = BotFactory().get_bot(channel_id)
            channel = bot.channel

            if visitor_id:
                visitors = ChatVisitor.objects.filter(id=visitor_id)
                if visitors:
                    visitor = visitors[0]

            if not visitor:
                visitor = ChatVisitor.objects.create(username=session_id[-8:], tenant_id=bot.tenant.id)
                visitor.save()

            session = Session(session_id, bot, visitor, channel)
        self.add(session)

        return session

    @staticmethod
    def has_visitor_cookie(request):
        http_cookies = request.COOKIES
        return http_cookies.get(conf.BOT_COOKIE_VISITOR_ID, '')
